import { useRef, MouseEvent, useEffect, useTransition } from "react";
import { DndProvider, useDrag, useDrop, DropTargetMonitor } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { TouchBackend } from "react-dnd-touch-backend";
import { Dialog, Toast, Form, Input } from "antd-mobile";
import Locale from "../locales";
import styles from "./home.module.scss";
import { useChatStore, ChatSession } from "@/store";
import { isTouchDevice } from "@/utils/utils";
import DeleteIcon from "../icons/delete.svg";
import StarIcon from "../icons/star-mini.svg";

type ItemType = {
  id: number;
  text: string;
};

type DragItem = {
  index: number;
  id: string;
  type: string;
};

interface IUpdateTopic {
  visible: boolean;
  session: ChatSession;
  onClose: () => void;
}
interface DndContainerProps {
  children: React.ReactNode;
}

export const DndContainer: React.FC<DndContainerProps> = ({ children }) => {
  const backend = isTouchDevice() ? TouchBackend : HTML5Backend;
  return (
    <DndProvider
      backend={backend}
      options={{
        enableMouseEvents: true,
        enableTouchEvents: true,
        delayTouchStart: 200,
        delay: 200,
      }}
    >
      {children}
    </DndProvider>
  );
};
export function ChatItem(props: {
  onClick?: () => void;
  onDelete?: () => void;
  moveItem: (dragIndex: number, hoverIndex: number) => void;
  title: string;
  count: number;
  item: ChatSession;
  index: number;
  time: string;
  selected: boolean;
  isCollect: boolean;
}) {
  const handleDelete = async (event: MouseEvent<HTMLDivElement>) => {
    event.stopPropagation();
    const result = await Dialog.confirm({
      content: Locale.Home.DeleteChat,
    });
    if (result) {
      props.onDelete?.();
    }
  };
  const ref = useRef<HTMLDivElement>(null);

  const [{ isOver }, drop] = useDrop({
    accept: "item",
    collect: (monitor: DropTargetMonitor) => ({
      isOver: monitor.isOver(),
    }),
    hover: (item: DragItem, monitor: DropTargetMonitor) => {
      if (!ref.current) {
        return;
      }

      const dragIndex = item.index;
      const hoverIndex = props.index;

      if (dragIndex === hoverIndex) {
        return;
      }

      props.moveItem(dragIndex, hoverIndex);
      item.index = hoverIndex;
    },
  });

  const [{ isDragging }, drag] = useDrag({
    type: "item",
    item: { type: "item", id: props.item.id, index: props.index },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
      dragOffset: monitor.getSourceClientOffset(),
    }),
  });

  drag(drop(ref));

  return (
    <div
      ref={ref}
      style={{
        opacity: isDragging ? 0.5 : 1,
      }}
      className={`${styles["chat-item"]} ${
        props.selected && styles["chat-item-selected"]
      } ${isOver && styles["chat-item-hover"]}`}
      onClick={(e) => {
        props.onClick?.();
      }}
    >
      <div className={styles["chat-item-title"]}>{props.title}</div>
      <div className={styles["chat-item-info"]}>
        <div className={styles["chat-item-count"]}>
          {props.isCollect && (
            <StarIcon className={styles["chat-item-count-star"]} />
          )}
          {Locale.ChatItem.ChatItemCount(props.count)}
        </div>
        <div className={styles["chat-item-date"]}>{props.time}</div>
      </div>

      <div className={styles["chat-item-delete"]} onClick={handleDelete}>
        <DeleteIcon />
      </div>
    </div>
  );
}
export function ChatList() {
  const {
    sessions,
    currentSessionIndex,
    selectSession,
    updateSession,
    removeSession,
    updateSessionIndex,
    updateConversationIndex,
  } = useChatStore();
  const [, startTransition] = useTransition();
  const moveItem = (dragIndex: number, hoverIndex: number) => {
    const dragItem = sessions[dragIndex];
    const newSessions = [...sessions];
    newSessions.splice(dragIndex, 1);
    newSessions.splice(hoverIndex, 0, dragItem);
    dragItem.id &&
      updateConversationIndex(dragItem.id, newSessions[hoverIndex + 1]?.id);
    startTransition(() => {
      updateSession(newSessions);
      updateSessionIndex(hoverIndex);
    });
  };

  return (
    <DndContainer>
      <div className={styles["chat-list"]}>
        {sessions.map((item, i) => {
          return (
            <ChatItem
              index={i}
              item={item}
              moveItem={moveItem}
              title={item.topic}
              isCollect={item.isCollect}
              time={item.lastUpdate}
              count={item.stat.charCount}
              key={i}
              selected={i === currentSessionIndex}
              onClick={() => selectSession(i)}
              onDelete={() => removeSession(i)}
            />
          );
        })}
      </div>
    </DndContainer>
  );
}

export function UpdateTopicdModal({ visible, session, onClose }: IUpdateTopic) {
  const [form] = Form.useForm();
  const { updateCurrentSessionName } = useChatStore();
  useEffect(() => {
    form.setFieldsValue({
      topic: session.topic,
    });
  }, [session, form]);

  const onSubmit = () => {
    return form
      .validateFields()
      .then((values) => {
        const { topic: newTopic } = values;
        if (newTopic === session.topic) {
          return;
        }
        return updateCurrentSessionName(session.id, newTopic);
      })
      .then(onClose);
  };
  return (
    <Dialog
      forceRender
      title="重命名对话"
      visible={visible}
      content={
        <Form form={form} layout="vertical">
          <Form.Item
            label="对话名称"
            name="topic"
            rules={[{ required: true, message: "对话名称不能为空" }]}
          >
            <Input placeholder="请输入对话名称" clearable />
          </Form.Item>
        </Form>
      }
      onClose={onClose}
      actions={[
        [
          {
            key: "cancel",
            text: "取消",
            onClick: () => {
              onClose();
            },
          },
          {
            key: "confirm",
            text: "确定",
            onClick: async () => {
              await onSubmit();
            },
          },
        ],
      ]}
    />
  );
}
